import { StartupModule } from '@boticord/startup'
import { UsersClientModule } from '@boticord/users-client'
import { Module } from '@nestjs/common'
import { ConfigModule, ConfigService } from '@nestjs/config'
import { RpcController } from './controllers/rpc.controller'
import { ResourcesClientModule } from '@boticord/resources-client'
import { BotService } from './services/bot.service'
import { CommandsService } from './services/commands.service'
import { BOT_CLIENT, BOT_CLIENT_OPTIONS, BotClientModule, BotClientModuleOptions } from '@boticord/bot-client'
import { ClientsModule, Transport } from '@nestjs/microservices'
import {
  ClientBuilder,
  GuildMembersCachingPolicy,
  IntentsUtil,
  MessagesCachingPolicy,
  PresenceActivityTypes,
} from 'discordoo'
import { DiscordooModule } from '@boticord/discordoo'
import { CustomRestProvider } from './services/custom-rest.provider'

@Module({
  imports: [
    StartupModule.forRoot('Bot'),
    DiscordooModule.forRootAsync({
      imports: [ ConfigModule ],
      inject: [ ConfigService ],
      useFactory: (config: ConfigService) => ({
        // BOT CONFIG IS HERE
        build: (b: ClientBuilder) => b
          .gateway({
            // specify all intents
            intents: IntentsUtil.NON_PRIVILEGED_NUMERIC,
            presence: {
              status: 'online',
              activities: [
                {
                  name: 'BotiCord v2 Open Beta',
                  type: PresenceActivityTypes.GAME,
                },
              ],
            },
            sharding: {
              totalShards: 8,
            },
          })
          .cache({
            members: {
              policies: [ GuildMembersCachingPolicy.NONE ],
            },
            messages: {
              policies: [ MessagesCachingPolicy.NONE ],
            },
          })
          .restProvider(CustomRestProvider),
        discordToken: config.getOrThrow<string>('DISCORD_TOKEN'),
      }),
    }),
    // ErisModule.registerAsync({
    //   imports: [ ConfigModule ],
    //   inject: [ ConfigService ],
    //   useFactory: (config: ConfigService) => {
    //     return ({
    //       token: config.getOrThrow('DISCORD_TOKEN'),
    //       intents: Constants.Intents.all | GatewayIntents.MESSAGE_CONTENT,
    //     })
    //   },
    // }),
    UsersClientModule.forRootAsync({
      imports: [ ConfigModule ],
      inject: [ ConfigService ],
      useFactory: (config: ConfigService) => ({
        natsServers: config.getOrThrow<string>('NATS_SERVERS').split(','),
      }),
    }),
    ResourcesClientModule.forRootAsync({
      imports: [ ConfigModule ],
      inject: [ ConfigService ],
      useFactory: (config: ConfigService) => ({
        natsServers: config.getOrThrow('NATS_SERVERS').split(','),
      }),
    }),
    BotClientModule.forRootAsync({
      imports: [ ConfigModule ],
      inject: [ ConfigService ],
      useFactory: (config: ConfigService) => ({
        natsServers: config.getOrThrow('NATS_SERVERS').split(','),
      }),
    }),
    ClientsModule.registerAsync([
      {
        name: BOT_CLIENT,
        inject: [ BOT_CLIENT_OPTIONS ],
        useFactory: (options: BotClientModuleOptions) => ({
          transport: Transport.NATS,
          options: {
            servers: options.natsServers,
          },
        }),
      },
    ]),
  ],
  controllers: [ RpcController ],
  providers: [ BotService, CommandsService ],
})
export class AppModule {}
